package club.pinea.pool;

import club.pinea.interfaces.TCPMessage;
import club.pinea.loader.CommandLoader;
import club.pinea.proto.BasicProto;
import club.pinea.proto.CommandProto;
import club.pinea.send.MessageSend;
import club.pinea.session.GlobalSessionContainer;
import club.pinea.session.IOSession;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * protobuf消息处理类
 */
@Component
public class ProtoPoolExecutor {

    Logger logger = LoggerFactory.getLogger(ProtoPoolExecutor.class);

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Resource
    private CommandLoader commandLoader;

    private Map<Integer, Integer> clientOvertimeMap = new ConcurrentHashMap<>();
    private final int MAX_OVERTIME = 3; // 超时次数超过该值则注销连接

    /**
     * 执行特定的任务
     *
     * @param session
     * @param message
     */
    public void doTask(IOSession session, BasicProto.BaseMessage message) {
        if (Objects.equals(message.getOrder(), CommandProto.Command.C_S_HEART_VALUE)) {
            BasicProto.HeartResponse heart = BasicProto.HeartResponse.newBuilder().build();
            MessageSend.sendToUser(heart, session);
        } else {
            threadPoolTaskExecutor.execute(() -> {
                try {
                    TCPMessage handler = commandLoader.getHandler(message.getOrder());
                    if (handler == null) {
                        MessageSend.sendToUser(MessageSend.errorRes("不能处理的请求：" + message.getOrder()), session);
                    } else {
                        handler.doMessage(message, session);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    MessageSend.sendToUser(MessageSend.errorRes(e), session);
                }
            });
        }
    }

    /**
     * 心跳检测不活跃
     *
     * @param session
     * @param evt
     */
    public void userEventTriggered(IOSession session, Object evt) {
        int sessionId = session.getSessionId();
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            if (e.state() == IdleState.READER_IDLE) {
                // 超过最大重试次数
                int overtimeTimes = clientOvertimeMap.containsKey(sessionId) ? clientOvertimeMap.get(sessionId) : 0;
                if (overtimeTimes < MAX_OVERTIME) {
                    addUserOvertime(session);
                } else {
                    logger.info(String.format("IP[%s] Session[%d] 读超时", session.getIp(), session.getSessionId()));
                    handlerRemoved(session);
                }
            }
        }
    }

    /**
     * 添加重试次数
     *
     * @param session
     */
    private void addUserOvertime(IOSession session) {
        int oldTimes = 0;
        if (clientOvertimeMap.containsKey(session.getSessionId())) {
            oldTimes = clientOvertimeMap.get(session.getSessionId());
        }
        clientOvertimeMap.put(session.getSessionId(), (int) (oldTimes + 1));
    }

    /**
     * 断开连接
     *
     * @param session
     */
    public void handlerRemoved(IOSession session) {
//        GlobalServerPlayerContainer.playerOffline(session, "userEventTriggered");
        GlobalSessionContainer.delIOSession(session);
        session.disConnect();
//        if (userId != 0) {
//            //控制将用户信息设置为暂离状态，可以随时登录回来
//            userService.UserLogout(userId, 3);
//        }
//        //将座位信息清空
//        if (seat != null) {
//            seat.setSeatStatus(0);
//            seat.setSeatUser(null);
//            seatService.updateSeat(seat, seat.getSeatId(), false);//更新数据库中的座位信息状态
//            seat = null;
//        }
    }
}
